import React, { forwardRef, useState, useRef, useImperativeHandle, Fragment, FC, PropsWithChildren } from "react";
import { Button, Col, Drawer, Form, Row, Space } from 'antd';
import { EllipsisOutlined, SearchOutlined } from '@ant-design/icons';
import { IOuterFilterProps, ITheme, FilterActionRef, FilterItem } from "../typing";

export interface FilterProps extends IOuterFilterProps {
  setFilter: (filter: any) => void;
  theme: ITheme;
}

const Filter = forwardRef<{ getFilterData: () => Promise<any> }, FilterProps>(({ setFilter, theme, maxWidth, moreFilterWidth, FilterContent, MoreFilterContent, searchBtnVisible = true, filterItems }, ref) => {
  const filterRef = useRef<FilterActionRef>()
  const moreFilterRef = useRef<FilterActionRef>();
  const [visible, setVisible] = useState(false);
  const divRef = useRef<HTMLDivElement>();

  const getFilterData = () => new Promise((resolve, reject) => {
    if (filterRef.current && moreFilterRef.current) {
      Promise.all([filterRef.current.getFormData(), moreFilterRef.current.getFormData()])
        .then(([filterValues, moreFilterValues]) => resolve({ ...filterValues, ...moreFilterValues }))
        .catch((e) => reject(e))
    } else if (filterRef.current) {
      filterRef.current.getFormData()
        .then((data) => resolve(data))
        .catch((e) => reject(e))
    } else {
      resolve({})
    }
  })

  useImperativeHandle(ref, () => ({ getFilterData, }));

  const updateFilter = () => {
    getFilterData()
      .then((resp) => setFilter(resp))
      .catch((e) => console.error("e->", e));
  }

  const isShowFilterForm = filterItems && filterItems.length > 0;
  const isShowFilterContent = !!FilterContent;

  return (
    <div className="filter" ref={divRef} style={{ display: "flex", justifyContent: "flex-start", width: "100%" }}>
      {isShowFilterForm && <FilterForm ref={filterRef} doSearch={updateFilter} items={filterItems} maxWidth={maxWidth} />}
      {isShowFilterContent && <FilterContent ref={filterRef} doSearch={updateFilter} />}
      {(isShowFilterForm || isShowFilterContent) && searchBtnVisible && <Button type="primary" onClick={() => updateFilter()} icon={<SearchOutlined />} style={{ marginLeft: 5 }}>搜索</Button>}

      {MoreFilterContent && <Fragment>
        <Button title="更多查询条件" type="primary" onClick={() => setVisible(!visible)} icon={<EllipsisOutlined />} style={{ marginLeft: 5 }} />
        <Drawer
          title="更多查询条件"
          width={moreFilterWidth}
          open={visible}
          onClose={() => setVisible(false)}
        >
          <MoreFilter
            theme={theme}
            setVisible={setVisible}
            updateFilter={updateFilter}
          >
            <MoreFilterContent ref={moreFilterRef} doSearch={updateFilter} />
          </MoreFilter>
        </Drawer>
      </Fragment>}
    </div>
  );
})


export default Filter;

interface MoreFilterProps {
  theme: ITheme;
  setVisible: (visible: boolean) => void;
  updateFilter: () => void;
}

const MoreFilter: FC<PropsWithChildren<MoreFilterProps>> = ({ setVisible, updateFilter, children }) => {

  return <Fragment>
    {children}
    <Row justify="center" style={{ marginTop: 5 }}>
      <Space>
        <Button
          type="primary"
          onClick={() => {
            setVisible(false);
            updateFilter();
          }}
          icon={<SearchOutlined />}
        >搜索</Button>
        <Button onClick={() => setVisible(false)}>取消</Button>
      </Space>
    </Row>
  </Fragment>
}

/**
 * 过滤条件表单
 */
const FilterForm = React.forwardRef<FilterActionRef, { doSearch: Function, items: FilterItem[], maxWidth: string }>(({ items, maxWidth }, actionRef) => {
  const [form] = Form.useForm();

  useImperativeHandle(actionRef, () => ({
    getFormData: () => new Promise((resolve, reject) => {
      form.validateFields()
        .then((data) => resolve(data))
        .catch((e) => reject(e));
    })
  }), [form]);

  const sumGridSpan = items.map(({ gridSpan }) => gridSpan).reduce((acr, cur) => acr + cur);

  return <Form form={form} component={false}>
    <Row style={{ width: maxWidth || "100%" }}>
      {items.map(({ title, name, component, gridSpan }, index) => <Col
        key={index}
        style={{ width: `${gridSpan / sumGridSpan * 100}%` }}
      >
        <Row align="middle" gutter={5} style={{ width: "100%" }} wrap={false}>
          <Col flex="none">{title}:</Col>
          <Col flex="auto">
            <Form.Item noStyle name={name}>
              {component}
            </Form.Item>
          </Col>
        </Row>
      </Col>)}
    </Row>
  </Form>
});
